Path Alias e Namespace
======================

O Yii utiliza path aliases (apelidos para caminhos) extensivamente. Um path alias, é um apelido associado
ao caminho de um diretório ou arquivo. Um path alias utiliza a sintaxe de ponto para separar seus itens, similar a forma largamente adotada em namespaces:

~~~
RootAlias.path.to.target
~~~

Onde `RootAlias` é o nome de um diretório existente. 

Ao usar o método [YiiBase::getPathOfAlias()], um apelido pode ser traduzido para o seu 
caminho correspondente. Por exemplo, `system.web.CController` seria 
traduzido para `yii/framework/web/CController`.

Ao executar o método [YiiBase::setPathOfAlias()], podemos definir novos apelidos para caminhos. 

Apelidos de Diretórios Raizes
-----------------------------

Por conveniência, o Yii já possui predefinidos os seguintes apelidos: 

 - `system`: refere-se ao diretório do Yii framework;
 - `zii`: refere-se ao diretório da [biblioteca Zii](/doc/guide/extension.use#zii-extensions);
 - `application`: refere-se ao [diretório base](/doc/guide/basics.application#application-base-directory) da aplicação;
 - `webroot`: refere-se ao diretório que contém o arquivo do [script de entrada](/doc/guide/basics.entry). 
 - `ext`: refere-se ao diretório que contém todas as [extensões](/doc/guide/extension.overview) de terceiros. 

Além disso, se a aplicação utiliza [módulos](/doc/guide/basics.module), 
um apelido de diretório raiz (root alias) é predefinido para cada módulo, 
apontando para o diretório base do módulo correspondente.
Por exemplo, se uma aplicação usa um módulo com ID `users`, o apelido de diretório raiz chamado `users`
será definido.

Importando Classes
------------------

A utilização de apelidos é muito conveniente para importar a definição de uma classe.
Por exemplo, se quisermos incluir a definição da classe [CController]
podemos fazer o seguinte:

~~~
[php]
Yii::import('system.web.CController');
~~~

O método [import|YiiBase::import] é mais eficiente que o `include` e o `require` do PHP.
Com ele, a definição da classe que está sendo importada 
não é incluída até que seja referenciada pela primeira vez (Implementado pelo mecanismo auto carregamento do PHP).
Importar o mesmo namespace várias vezes, também é muito mais rápido do que utilizar o `include_once`
e o `require_once`.

> Tip|Dica: Quando referenciamos uma das classes do Yii Framework, não precisamos 
importa-la ou inclui-la. Todas as classes Yii são pré-importadas.

###Usando mapa de Class

A partir da versão 1.1.5, o Yii permite que as classes possam ser pré-importadas através de um mecanismo
de mapeamento de classe que também é usado por classes Yii.
As classes pré-importadas podem ser usadas em qualquer lugar na aplicação Yii sem ser
explicitamente importadas ou incluídas. Este recurso é muito útil para uma biblioteca ou framework 
que é construído em cima do Yii.

Para pré-importar um conjunto de classes, o seguinte código deve ser executado antes
de chamar o [CWebApplication::run()]:

~~~
[php]
Yii::$classMap=array(
	'ClassName1' => 'path/to/ClassName1.php',
	'ClassName2' => 'path/to/ClassName2.php',
	......
);
~~~

Importando Diretórios
---------------------

Podemos também utilizar a seguinte sintaxe para importar todo um diretório de uma só vez, de forma que 
os arquivos de classe dentro dele sejam automaticamente incluídos, quando necessário.


~~~
[php]
Yii::import('system.web.*');
~~~

Além do método [import|YiiBase::import], apelidos são utilizados em vários outros 
locais para se referir a classes. Por exemplo, um apelido pode ser passado para o método 
[Yii::createComponent()] para criar uma instância da classe informada,
mesmo que o arquivo da classe ainda não tenha sido incluído.

Namespace
---------

Não confunda um path alias com um namespace. Um namespace refere-se a um agrupamento lógico
de nomes de classes para que eles possam ser diferenciadas de outros 
nomes das classes, mesmo que eles sejam iguais. Já um path alias é utilizado para 
referenciar um arquivo de classe ou um diretório. Um path alias não conflita com um 
namespace.

> Tip|Dica: Como o PHP, antes da versão 5.3.0, não dá suporte a namespaces, 
você não pode criar instâncias de duas classes que tenham o mesmo 
nome, mas definições diferentes. Por isso, todas as classes do Yii framework 
são prefixadas com uma letra "C" (que significa 'class'), de modo que elas possam 
ser diferenciadas das classes definidas pelo usuário. Recomenda-se que o 
prefixo "C" seja reservado somente para utilização do Yii framework, e que classes criadas pelos usuário 
sejam prefixadas com outras letras.


Classes com Namespace
---------------------

Uma classe com namespace refere-se a uma classe declarada dentro de um espaço não-global.
Por exemplo, a classe `application\components\GoogleMap` é declarada dentro do namespace
`application\components`. O uso das classes com namespace requer PHP 5.3.0 ou superior.

A partir da versão 1.1.5, é possível a utilização de uma classe namespaced sem
incluir explicitamente. Por exemplo, podemos criar uma nova instância do 
`application\components\GoogleMap` sem incluir o arquivo de classe correspondente
explicitamente. Isso é possível com o mecanismo de auto carregamento das classes Yii.

Afim de ser capaz de carregar automaticamente uma classe com namespace, o namespace 
deve ser nomeado de forma semelhante a nomear um path alias. 
Por exemplo, a classe `application\components\GoogleMap` deve ser armazenada em um 
arquivo que pode ser apelidado como `application.components.GoogleMap`

Então, para usar namespace personalizado começando com, por exemplo `\mynamespace` aonde
as classes são localizadas em  `/var/www/common/mynamespace/`
a única coisa que você deve fazer é definir um path alias, como o seguinte:


~~~
[php]
Yii::setPathOfAlias('mynamespace', '/var/www/common/mynamespace/');
~~~


Controles com Namespace
-----------------------

Por padrão Yii usa controladores do namespace global. Essas classes estão localizados sob 
`protected/controllers`. Você pode alterar esse comportamento de duas maneiras diferentes:
usando `controllerMap` e usando `controllerNamespace`. O primeiro permite que você use 
controles com namespaces diferentes. O último requer menos configuração para definir um namespace 
para todos os controles.

### Usando `controllerMap`

A melhor maneira de mudar o mapa do controle é usar o arquivo de configuração
(`protected/config/main.php`):

~~~
// adding "mynamespace" namespace
Yii::setPathOfAlias('mynamespace', '/var/www/common/mynamespace/');

return array(
	'basePath'=>dirname(__FILE__).DIRECTORY_SEPARATOR.'..',
	'name'=>'My Web Application',

	'controllerMap' => array(
		'test' => '\mynamespace\controllers\TestController',
	),
~~~

Quando o usuário tenta carregar qualquer um dos controles definidos em `controllerMap`,
Yii carrega as classes especificadas, ignorando o método de carregamento normal do controle.
No caso de `test` o Yii irá carregar a classe `\mynamespace\controllers\TestController` localizada em
`/var/www/common/mynamespace/controllers/TestController.php`.

Observe que o código do controle deve ter um namespace definido:

~~~
[php]
// define namespace:
namespace mynamespace\controllers;

// since class is now under namespace, global namespace
// should be referenced explicitly using "\":
class TestController extends \CController
{
	public function actionIndex()
	{
		echo 'This is TestController from \mynamespace\controllers';
	}
}
~~~

### Usando `controllerNamespace`

Uma vez que a aplicação é um módulo em si, é possível utilizar a propriedade `controllerNamespace`
da mesma maneira como descrita em "Módulos com namespace" logo abaixo.

Módulos com namespace
---------------------

Às vezes é útil utilizar namespace para o módulo completo. Por exemplo, se você quiser colocar 
`testmodule` em `\mynamespace\modules\testmodule` apontando para
`/var/www/common/mynamespace/modules/testmodule` você deveria primeiro criar a seguinte 
estrutura de arquivo:

~~~
/var/www/common/mynamespace/modules
  testmodule
    controllers
      DefaultController.php
    views
      default
        index.php
    TestmoduleModule.php
~~~

`index.php` é mesma visão que no modulo normal. `TestmoduleModule.php` e
`DefaultController.php` estão com namespace.

`TestmoduleModule.php`:

~~~
[php]
// define namespace:
namespace mynamespace\modules\testmodule;

// since class is now under namespace, global namespace
// should be referenced explicitly using "\":
class TestmoduleModule extends \CWebModule
{
	// setting non-global controllers namespace (also can be done via config)
	public $controllerNamespace = '\mynamespace\modules\testmodule\controllers';

	// usual module code
}
~~~

`DefaultController.php`:

~~~
[php]
<?php

// define namespace:
namespace mynamespace\modules\testmodule\controllers;

// since class is now under namespace, global namespace
// should be referenced explicitly using "\":
class DefaultController extends \Controller
{
	public function actionIndex()
	{
		$this->render('index');
	}
}
~~~

Agora, a única coisa que resta é adicionar o módulo na aplicação.
A melhor maneira de fazer isso é especificá-la no arquivo de configuração do aplicativo (`protected/config/main.php`):

~~~
[php]
// adding "mynamespace" namespace
Yii::setPathOfAlias('mynamespace', '/var/www/common/mynamespace/');

return array(
	'basePath'=>dirname(__FILE__).DIRECTORY_SEPARATOR.'..',
	'name'=>'My Web Application',

	'modules'=>array(
		'testmodule' => array(
			'class' => '\mynamespace\modules\testmodule\TestModuleModule',
		),
	),
~~~

<div class="revision">$Id$</div>
